<template>
	<view class="container">
		<!-- 设备选择 -->
		<view class="device-selector">
			<uni-data-select 
				v-model="selectedDevice" 
				:localdata="deviceList"
				placeholder="选择监测设备"
				@change="onDeviceChange"
			></uni-data-select>
		</view>
		
        <!-- 实时数据卡片 -->
        <view class="data-cards">
            <view class="data-card" v-for="(item, index) in realtimeData" :key="index">
                <view class="card-header">
                    <view class="card-left">
                        <view class="card-icon" :class="iconClass(item.name)">
                            <uni-icons :type="iconType(item.name)" size="20" color="#fff" />
                        </view>
                        <text class="card-title">{{ item.name }}</text>
                    </view>
                    <view class="status-indicator" :class="item.status"></view>
                </view>
                <view class="card-body">
                    <text class="data-value">{{ item.value }}<text class="data-unit">{{ item.unit }}</text></text>
                </view>
            </view>
        </view>
		
		<!-- 警告标准说明 -->
		<view class="warning-standards">
			<view class="standards-header">
				<uni-icons type="info" size="18" color="#007aff" />
				<text class="standards-title">水质监测标准</text>
			</view>
			<view class="standards-content">
				<view class="standard-item">
					<text class="standard-label">pH值：</text>
					<text class="standard-range normal">6.5 - 8.5</text>
					<text class="standard-unit">(正常范围)</text>
				</view>
				<view class="standard-item">
					<text class="standard-label">温度：</text>
					<text class="standard-range normal">20 - 30</text>
					<text class="standard-unit">°C (正常范围)</text>
				</view>
				<view class="standard-item">
					<text class="standard-label">浊度：</text>
					<text class="standard-range normal">< 3000</text>
					<text class="standard-unit">NTU (正常范围)</text>
				</view>
			</view>
		</view>
		
		<!-- 异常状态显示 -->
		<view class="anomaly-alert" v-if="currentAnomaly" @click="goToAlertDetail">
			<view class="anomaly-alert-content">
				<uni-icons type="warning" size="20" color="#e74c3c"></uni-icons>
				<text class="anomaly-alert-text">{{ currentAnomaly.type }}</text>
				<uni-icons type="arrowright" size="16" color="#7f8c8d"></uni-icons>
			</view>
		</view>
		
		<!-- 数据图表 -->
		<view class="chart-section">
			<view class="chart-header">
				<text class="chart-title">数据趋势</text>
			</view>
			
			<!-- pH值图表 -->
			<view class="chart-item">
				<view class="chart-item-header">
					<text class="chart-item-title">pH值趋势</text>
					<text class="chart-item-unit">单位: pH</text>
				</view>
				<view class="chart-container">
					<view id="phChartDiv" class="chart-canvas"></view>
				</view>
			</view>
			
			<!-- 温度图表 -->
			<view class="chart-item">
				<view class="chart-item-header">
					<text class="chart-item-title">温度趋势</text>
					<text class="chart-item-unit">单位: °C</text>
				</view>
				<view class="chart-container">
					<view id="tempChartDiv" class="chart-canvas"></view>
				</view>
			</view>
			
			<!-- 浊度图表 -->
			<view class="chart-item">
				<view class="chart-item-header">
					<text class="chart-item-title">浊度趋势</text>
					<text class="chart-item-unit">单位: NTU</text>
				</view>
				<view class="chart-container">
					<view id="turbidityChartDiv" class="chart-canvas"></view>
				</view>
			</view>
		</view>
		
		<!-- 实时数据流 -->
		<view class="table-section">
			<view class="table-header">
				<text class="table-title">实时数据流</text>
				<view class="connection-status" :class="wsConnected ? 'connected' : 'disconnected'">
					<text class="status-text">{{ wsConnected ? '已连接' : '连接中...' }}</text>
				</view>
			</view>
			<view class="table-content">
				<view class="table-row header">
					<text class="col-time">时间</text>
					<text class="col-ph">pH</text>
					<text class="col-temp">温度</text>
					<text class="col-turb">浊度</text>
					<text class="col-status">状态</text>
				</view>
				<view class="table-row" v-for="(item, index) in realtimeHistoryData" :key="index">
					<text class="col-time">{{ item.time }}</text>
					<text class="col-ph">{{ item.ph }}</text>
					<text class="col-temp">{{ item.temp }}°C</text>
					<text class="col-turb">{{ item.turbidity }}</text>
					<text class="col-status" :class="item.status">{{ item.statusText }}</text>
				</view>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { onShow, onHide } from '@dcloudio/uni-app'
import { BASE_URL, get } from '@/api/request.js'
import { useAlertStore } from '@/stores/alert.js'
import * as echarts from 'echarts'

// 响应式数据
const selectedDevice = ref('ESP8266_001')
const realtimeData = ref([
	{
		name: 'pH值',
		value: 7.2,
		unit: '',
        status: 'normal'
	},
	{
		name: '温度',
		value: 22.5,
		unit: '°C',
        status: 'normal'
	},
	{
		name: '浊度',
		value: 1.8,
		unit: 'NTU',
        status: 'normal'
	},
    
])

let ws = null

const deviceList = ref([
	{ value: 'ESP8266_001', text: '监测点ESP8266_001' },
	{ value: 'device1', text: '监测点001' },
	{ value: 'device2', text: '监测点002' },
	{ value: 'device3', text: '监测点003' }
])

const historyData = ref([])
const realtimeHistoryData = ref([])
const wsConnected = ref(false)
const currentAnomaly = ref(null)

// 警告冷却机制
const alertCooldown = ref({}) // 存储每种警告类型的最后触发时间
const COOLDOWN_DURATION = 30000 // 30秒冷却时间（毫秒）

// 使用alert store
const alertStore = useAlertStore()

let phChartInstance = null
let tempChartInstance = null
let turbidityChartInstance = null

let updateTimer = null

onMounted(() => {
    loadData()
    initWebSocket()
    nextTick(initAllCharts)
})

onShow(() => {
    // 页面可见时确保WebSocket连接正常
    console.log('页面显示，检查WebSocket连接')
    if (!ws || ws.readyState !== WebSocket.OPEN) {
        initWebSocket()
    }
})

onHide(() => {
    // 页面隐藏时保持WebSocket连接，但停止图表渲染
    console.log('页面隐藏，保持WebSocket连接')
    disposeAllCharts()
})

onUnmounted(() => {
    if (ws) {
        ws.close()
        ws = null
    }
    disposeAllCharts()
})

// 加载数据（初始加载立即请求一次）
const loadData = async () => {
	await fetchToday()
}


// 移除定时器机制，完全依赖WebSocket实时数据

// WebSocket 实时数据
const initWebSocket = () => {
    try {
        const wsUrl = BASE_URL.replace('http', 'ws') + '/ws/water-quality'
        ws = new WebSocket(wsUrl)
        
        ws.onopen = () => {
            console.log('WebSocket连接已建立')
            wsConnected.value = true
        }
        
        ws.onmessage = (evt) => {
            try {
                const msg = JSON.parse(evt.data)
                applyRealtimeMessage(msg)
                // 将实时数据添加到历史流中
                addToRealtimeHistory(msg)
            } catch (e) {
                console.error('WebSocket消息解析失败:', e)
            }
        }
        
        ws.onclose = () => {
            console.log('WebSocket连接已关闭，5秒后重连')
            wsConnected.value = false
            setTimeout(initWebSocket, 5000)
        }
        
        ws.onerror = (error) => {
            console.error('WebSocket连接错误:', error)
            wsConnected.value = false
        }
    } catch (e) {
        console.error('WebSocket初始化失败:', e)
        wsConnected.value = false
    }
}

const applyRealtimeMessage = (msg) => {
    const mapping = {
        'pH值': 'phValue',
        '温度': 'temperature',
        '浊度': 'turbidity'
    }
    realtimeData.value = realtimeData.value.map(item => {
        const key = mapping[item.name]
        if (key && typeof msg[key] === 'number') {
            const old = item.value
            item.value = Math.round(msg[key] * 10) / 10
            if (item.name === 'pH值') {
                item.status = item.value >= 6.5 && item.value <= 8.5 ? 'normal' : 'warning'
            } else if (item.name === '温度') {
                item.status = item.value >= 20 && item.value <= 30 ? 'normal' : 'warning'
            } else if (item.name === '浊度') {
                item.status = item.value < 3000 ? 'normal' : 'warning'
            }
        }
        return item
    })
}

// 添加实时数据到历史流
const addToRealtimeHistory = (msg) => {
    const now = new Date()
    const timeStr = now.toLocaleTimeString('zh-CN', { 
        hour12: false, 
        hour: '2-digit', 
        minute: '2-digit',
        second: '2-digit'
    })
    
    // 检查是否已存在相同时间戳的记录，避免重复
    const existingRecord = realtimeHistoryData.value.find(record => record.time === timeStr)
    if (existingRecord) {
        console.log('检测到重复时间戳，跳过添加:', timeStr)
        return
    }
    
    // 检查时间是否连续，如果不连续则记录警告
    if (realtimeHistoryData.value.length > 0) {
        const lastRecord = realtimeHistoryData.value[0]
        const lastTime = new Date(`1970-01-01 ${lastRecord.time}`)
        const currentTime = new Date(`1970-01-01 ${timeStr}`)
        const timeDiff = (currentTime - lastTime) / 1000
        
        if (timeDiff > 2) {
            console.warn('⚠️ 时间间隔异常:', lastRecord.time, '->', timeStr, '间隔:', timeDiff, '秒')
        }
    }
    
    // 判断整体状态
    let overallStatus = 'normal'
    let statusText = '正常'
    
    const ph = msg.phValue || 0
    const temp = msg.temperature || 0
    const turb = msg.turbidity || 0
    
    if (ph < 6.5 || ph > 8.5 || temp < 20 || temp > 30 || turb >= 3000) {
        overallStatus = 'warning'
        statusText = '异常'
        
        // 检测具体异常类型并记录
        checkAndRecordAnomaly(ph, temp, turb, timeStr)
    } else {
        // 数据正常时也要检查并清除异常状态
        checkAndRecordAnomaly(ph, temp, turb, timeStr)
    }
    
    const newRecord = {
        time: timeStr,
        ph: ph.toFixed(1),
        temp: temp.toFixed(1),
        turbidity: turb.toFixed(1),
        status: overallStatus,
        statusText: statusText
    }
    
    // 添加到历史流开头（最新的在上面）
    realtimeHistoryData.value.unshift(newRecord)
    
    // 限制历史记录数量，保持最新的50条
    if (realtimeHistoryData.value.length > 50) {
        realtimeHistoryData.value = realtimeHistoryData.value.slice(0, 50)
    }
    
    // 更新图表数据
    updateChartDataFromRealtime()
}

// 检测并记录异常数据
const checkAndRecordAnomaly = (ph, temp, turb, timeStr) => {
    // 清理过期的冷却时间
    cleanupExpiredCooldowns()
    
    const anomalies = []
    
    // 检测pH值异常
    if (ph < 6.5 || ph > 8.5) {
        anomalies.push({
            type: 'pH值异常',
            indicator: 'PH',
            currentValue: ph.toFixed(1),
            normalRange: '6.5-8.5',
            severity: ph < 6.0 || ph > 9.0 ? 'high' : 'medium',
            description: `pH值${ph.toFixed(1)}超出正常范围(6.5-8.5)`
        })
        console.log(`🚨 pH值异常: ${ph} (范围: 6.5-8.5)`)
    } else {
        console.log(`✅ pH值正常: ${ph} (范围: 6.5-8.5)`)
    }
    
    // 检测温度异常
    if (temp < 20 || temp > 30) {
        anomalies.push({
            type: '温度异常',
            indicator: 'TEMP',
            currentValue: temp.toFixed(1),
            normalRange: '20-30°C',
            severity: temp < 15 || temp > 35 ? 'high' : 'medium',
            description: `温度${temp.toFixed(1)}°C超出正常范围(20-30°C)`
        })
        console.log(`🚨 温度异常: ${temp}°C (范围: 20-30°C)`)
    } else {
        console.log(`✅ 温度正常: ${temp}°C (范围: 20-30°C)`)
    }
    
    // 检测浊度异常
    if (turb >= 3000) {
        anomalies.push({
            type: '浊度异常',
            indicator: 'TURBIDITY',
            currentValue: turb.toFixed(1),
            normalRange: '<3000 NTU',
            severity: turb >= 5000 ? 'high' : 'medium',
            description: `浊度${turb.toFixed(1)}NTU超出正常范围(<3000 NTU)`
        })
        console.log(`🚨 浊度异常: ${turb}NTU (范围: <3000 NTU)`)
    } else {
        console.log(`✅ 浊度正常: ${turb}NTU (范围: <3000 NTU)`)
    }
    
    // 记录异常数据
    console.log(`🔍 异常检测结果: pH=${ph}, 温度=${temp}, 浊度=${turb}, 异常数量=${anomalies.length}`)
    
    if (anomalies.length > 0) {
        // 设置当前异常状态（显示最新的异常）
        const latestAnomaly = anomalies[0]
        currentAnomaly.value = {
            id: Date.now() + Math.random(),
            time: timeStr,
            type: latestAnomaly.type,
            indicator: latestAnomaly.indicator,
            currentValue: latestAnomaly.currentValue,
            normalRange: latestAnomaly.normalRange,
            severity: latestAnomaly.severity,
            description: latestAnomaly.description,
            status: 'unhandled',
            createTime: new Date().toISOString(),
            deviceId: selectedDevice.value || 'ESP8266_001',
            device: selectedDevice.value ? `监测点${selectedDevice.value}` : '监测点ESP8266_001'
        }
        console.log('🚨 设置异常状态:', currentAnomaly.value.type)
    } else {
        // 如果没有异常，清除当前异常状态
        if (currentAnomaly.value) {
            console.log('✅ 数据恢复正常，清除异常状态')
        }
        currentAnomaly.value = null
    }
    
    anomalies.forEach(anomaly => {
        const anomalyRecord = {
            id: Date.now() + Math.random(),
            time: timeStr,
            type: anomaly.type,
            indicator: anomaly.indicator,
            currentValue: anomaly.currentValue,
            normalRange: anomaly.normalRange,
            severity: anomaly.severity,
            description: anomaly.description,
            status: 'unhandled',
            createTime: new Date().toISOString(),
            deviceId: selectedDevice.value || 'ESP8266_001',
            device: selectedDevice.value ? `监测点${selectedDevice.value}` : '监测点ESP8266_001'
        }
        
        // 检查冷却机制
        if (isAlertInCooldown(anomaly.type)) {
            console.log(`警告冷却中: ${anomaly.type}，跳过通知`)
            return // 跳过这个异常的通知
        }
        
        // 更新冷却时间
        updateAlertCooldown(anomaly.type)
        
        // 显示异常通知
        showAnomalyNotification(anomalyRecord)
        
        // 实时告警已通过WebSocket统一处理，这里不再重复发送
        
        // 发送异常数据到后端（如果有API）
        sendAnomalyToBackend(anomalyRecord)
    })
}

// 显示异常通知
const showAnomalyNotification = (anomaly) => {
    const severityColors = {
        low: '#f39c12',
        medium: '#e67e22', 
        high: '#e74c3c'
    }
    
    const severityTexts = {
        low: '轻微',
        medium: '中等',
        high: '严重'
    }
    
    console.log(`🚨 触发异常通知: ${anomaly.type} [${severityTexts[anomaly.severity]}]`)
    
    uni.showToast({
        title: `${anomaly.type}`,
        icon: 'none',
        duration: 3000,
        mask: true
    })
    
    // 可以添加更详细的通知
    console.log(`异常检测: ${anomaly.description} [${severityTexts[anomaly.severity]}]`)
}

// 记录异常数据（后端已有自动异常检测机制）
const sendAnomalyToBackend = async (anomaly) => {
    try {
        // 后端DeviceController已经自动检测异常并保存到数据库
        // 这里只需要在前端记录异常信息用于界面显示
        console.log('异常数据已记录:', anomaly)
        console.log('后端已自动检测并保存异常数据到数据库')
    } catch (error) {
        console.error('记录异常数据失败:', error)
    }
}

// 从实时数据更新图表
const updateChartDataFromRealtime = () => {
    if (realtimeHistoryData.value.length === 0) return
    
    // 取最新的20条数据用于图表显示
    const chartData = realtimeHistoryData.value.slice(0, 20).reverse() // 反转以保持时间顺序
    
    const categories = chartData.map(item => item.time)
    const phSeries = chartData.map(item => parseFloat(item.ph))
    const tempSeries = chartData.map(item => parseFloat(item.temp))
    const turbSeries = chartData.map(item => parseFloat(item.turbidity))
    
    // 渲染图表
    renderPhChart(categories, phSeries)
    renderTempChart(categories, tempSeries)
    renderTurbidityChart(categories, turbSeries)
}

// 更新实时数据
const updateRealtimeData = () => {
    realtimeData.value.forEach(item => {
		// 模拟数据变化
		const variation = (Math.random() - 0.5) * 0.2
		item.value = Math.round((item.value + variation) * 10) / 10
		
		// 判断状态
		if (item.name === 'pH值') {
			item.status = item.value >= 6.5 && item.value <= 8.5 ? 'normal' : 'warning'
		} else if (item.name === '温度') {
			item.status = item.value >= 20 && item.value <= 25 ? 'normal' : 'warning'
		} else if (item.name === '浊度') {
			item.status = item.value < 3000 ? 'normal' : 'warning'
        }
	})
}

// 更新图表数据（由后端返回的数据驱动，或基于今日数据本地筛选）
const updateChartData = (rows = []) => {
    const normalize = (arr) => (Array.isArray(arr) ? arr : [])
    // 基础清洗
    let cleaned = normalize(rows)
        .filter(r => r && r.time)
        .map(r => ({
            time: r.time,
            ph: safeNum(r.ph),
            temp: safeNum(r.temp),
            turbidity: safeNum(r.turbidity)
        }))
    // 仅保留至少一个有效数值的点
    cleaned = cleaned.filter(r => isFinite(r.ph) || isFinite(r.temp) || isFinite(r.turbidity))

    // 兜底：若为空，用今日数据前20条
    if (cleaned.length === 0) {
        cleaned = normalize(historyData.value)
            .slice(0, 20)
            .map(r => ({
                time: r.time,
                ph: safeNum(r.ph),
                temp: safeNum(r.temp),
                turbidity: safeNum(r.turbidity)
            }))
            .filter(r => isFinite(r.ph) || isFinite(r.temp) || isFinite(r.turbidity))
    }

    // 再兜底：至少保证两点
    if (cleaned.length === 1) cleaned = cleaned.concat(cleaned)

    if (cleaned.length === 0) {
        // 渲染空数据图表
        renderPhChart([''], [0])
        renderTempChart([''], [0])
        renderTurbidityChart([''], [0])
        return
    }

    // 为了更稳定的绘制，将数据按时间升序排列
    const asc = [...cleaned].sort((a, b) => parseHmToMinutes(a.time) - parseHmToMinutes(b.time))
    const categories = asc.map(r => r.time)
    const phSeries = asc.map(r => (isFinite(r.ph) ? r.ph : null))
    const tempSeries = asc.map(r => (isFinite(r.temp) ? r.temp : null))
    const turbSeries = asc.map(r => (isFinite(r.turbidity) ? r.turbidity : null))

    // 渲染三个独立的图表
    renderPhChart(categories, phSeries)
    renderTempChart(categories, tempSeries)
    renderTurbidityChart(categories, turbSeries)
}

// 初始化所有图表
const initAllCharts = () => {
    initPhChart()
    initTempChart()
    initTurbidityChart()
}

// 初始化pH值图表
const initPhChart = () => {
    const el = document.getElementById('phChartDiv')
    if (!el) return
    if (phChartInstance) {
        phChartInstance.dispose()
    }
    phChartInstance = echarts.init(el)
}

// 初始化温度图表
const initTempChart = () => {
    const el = document.getElementById('tempChartDiv')
    if (!el) return
    if (tempChartInstance) {
        tempChartInstance.dispose()
    }
    tempChartInstance = echarts.init(el)
}

// 初始化浊度图表
const initTurbidityChart = () => {
    const el = document.getElementById('turbidityChartDiv')
    if (!el) return
    if (turbidityChartInstance) {
        turbidityChartInstance.dispose()
    }
    turbidityChartInstance = echarts.init(el)
}

// 渲染pH值图表
const renderPhChart = (categories, data) => {
    if (!phChartInstance) {
        initPhChart()
    }
    if (!phChartInstance) return
    
    const option = {
        tooltip: {
            trigger: 'axis',
            axisPointer: { type: 'cross' },
            confine: true,
            formatter: (params) => {
                if (!params || params.length === 0) return ''
                const time = params[0].axisValue
                const value = params[0].data ?? '-'
                return `${time}<br/>pH值: ${value}`
            }
        },
        color: ['#3498db'],
        grid: { left: 50, right: 30, top: 30, bottom: 60, containLabel: true },
        xAxis: { 
            type: 'category', 
            data: categories, 
            boundaryGap: false,
            axisLabel: { 
                formatter: (v) => v,
                fontSize: 11,
                color: '#666',
                rotate: 0
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd'
                }
            },
            axisPointer: { 
                label: { 
                    show: true,
                    fontSize: 12
                } 
            }
        },
        yAxis: { 
            type: 'value', 
            splitNumber: 6,
            name: 'pH',
            nameLocation: 'middle',
            nameGap: 40,
            scale: false,
            min: 'dataMin',
            max: 'dataMax',
            axisLabel: {
                fontSize: 12,
                color: '#666'
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd'
                }
            },
            splitLine: {
                lineStyle: {
                    color: '#f0f0f0',
                    type: 'dashed'
                }
            }
        },
        dataZoom: [
            { 
                type: 'inside', 
                throttle: 30,
                moveOnMouseMove: true,
                moveOnMouseWheel: true,
                zoomOnMouseWheel: true,
                zoomOnTouch: true,
                moveOnTouch: true,
                preventDefaultMouseMove: true,
                xAxisIndex: 0,
                yAxisIndex: 'none',
                filterMode: 'filter'
            }
        ],
        series: [{
            name: 'pH值',
            type: 'line',
            smooth: true,
            showSymbol: false,
            connectNulls: true,
            lineStyle: {
                width: 2.5,
                shadowBlur: 3,
                shadowColor: 'rgba(52,152,219,0.3)'
            },
            emphasis: { 
                focus: 'series',
                lineStyle: {
                    width: 3.5
                }
            },
            data: data
        }]
    }
    phChartInstance.setOption(option, true)
}

// 渲染温度图表
const renderTempChart = (categories, data) => {
    if (!tempChartInstance) {
        initTempChart()
    }
    if (!tempChartInstance) return
    
    const option = {
        tooltip: {
            trigger: 'axis',
            axisPointer: { type: 'cross' },
            confine: true,
            formatter: (params) => {
                if (!params || params.length === 0) return ''
                const time = params[0].axisValue
                const value = params[0].data ?? '-'
                return `${time}<br/>温度: ${value}°C`
            }
        },
        color: ['#e74c3c'],
        grid: { left: 50, right: 30, top: 30, bottom: 60, containLabel: true },
        xAxis: { 
            type: 'category', 
            data: categories, 
            boundaryGap: false,
            axisLabel: { 
                formatter: (v) => v,
                fontSize: 11,
                color: '#666',
                rotate: 0
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd'
                }
            },
            axisPointer: { 
                label: { 
                    show: true,
                    fontSize: 12
                } 
            }
        },
        yAxis: { 
            type: 'value', 
            splitNumber: 6,
            name: '°C',
            nameLocation: 'middle',
            nameGap: 40,
            scale: false,
            min: 'dataMin',
            max: 'dataMax',
            axisLabel: {
                fontSize: 12,
                color: '#666'
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd'
                }
            },
            splitLine: {
                lineStyle: {
                    color: '#f0f0f0',
                    type: 'dashed'
                }
            }
        },
        dataZoom: [
            { 
                type: 'inside', 
                throttle: 30,
                moveOnMouseMove: true,
                moveOnMouseWheel: true,
                zoomOnMouseWheel: true,
                zoomOnTouch: true,
                moveOnTouch: true,
                preventDefaultMouseMove: true,
                xAxisIndex: 0,
                yAxisIndex: 'none',
                filterMode: 'filter'
            }
        ],
        series: [{
            name: '温度',
            type: 'line',
            smooth: true,
            showSymbol: false,
            connectNulls: true,
            lineStyle: {
                width: 2.5,
                shadowBlur: 3,
                shadowColor: 'rgba(231,76,60,0.3)'
            },
            emphasis: { 
                focus: 'series',
                lineStyle: {
                    width: 3.5
                }
            },
            data: data
        }]
    }
    tempChartInstance.setOption(option, true)
}

// 渲染浊度图表
const renderTurbidityChart = (categories, data) => {
    if (!turbidityChartInstance) {
        initTurbidityChart()
    }
    if (!turbidityChartInstance) return
    
    const option = {
        tooltip: {
            trigger: 'axis',
            axisPointer: { type: 'cross' },
            confine: true,
            formatter: (params) => {
                if (!params || params.length === 0) return ''
                const time = params[0].axisValue
                const value = params[0].data ?? '-'
                return `${time}<br/>浊度: ${value}NTU`
            }
        },
        color: ['#9b59b6'],
        grid: { left: 50, right: 30, top: 30, bottom: 60, containLabel: true },
        xAxis: { 
            type: 'category', 
            data: categories, 
            boundaryGap: false,
            axisLabel: { 
                formatter: (v) => v,
                fontSize: 11,
                color: '#666',
                rotate: 0
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd'
                }
            },
            axisPointer: { 
                label: { 
                    show: true,
                    fontSize: 12
                } 
            }
        },
        yAxis: { 
            type: 'value', 
            splitNumber: 6,
            name: 'NTU',
            nameLocation: 'middle',
            nameGap: 40,
            scale: false,
            min: 'dataMin',
            max: 'dataMax',
            axisLabel: {
                fontSize: 12,
                color: '#666'
            },
            axisLine: {
                lineStyle: {
                    color: '#ddd'
                }
            },
            splitLine: {
                lineStyle: {
                    color: '#f0f0f0',
                    type: 'dashed'
                }
            }
        },
        dataZoom: [
            { 
                type: 'inside', 
                throttle: 30,
                moveOnMouseMove: true,
                moveOnMouseWheel: true,
                zoomOnMouseWheel: true,
                zoomOnTouch: true,
                moveOnTouch: true,
                preventDefaultMouseMove: true,
                xAxisIndex: 0,
                yAxisIndex: 'none',
                filterMode: 'filter'
            }
        ],
        series: [{
            name: '浊度',
            type: 'line',
            smooth: true,
            showSymbol: false,
            connectNulls: true,
            lineStyle: {
                width: 2.5,
                shadowBlur: 3,
                shadowColor: 'rgba(155,89,182,0.3)'
            },
            emphasis: { 
                focus: 'series',
                lineStyle: {
                    width: 3.5
                }
            },
            data: data
        }]
    }
    turbidityChartInstance.setOption(option, true)
}

// 清理所有图表
const disposeAllCharts = () => {
    if (phChartInstance) {
        phChartInstance.dispose()
        phChartInstance = null
    }
    if (tempChartInstance) {
        tempChartInstance.dispose()
        tempChartInstance = null
    }
    if (turbidityChartInstance) {
        turbidityChartInstance.dispose()
        turbidityChartInstance = null
    }
}

const safeNum = (v) => {
    if (v === null || v === undefined) return NaN
    const s = String(v).trim()
    // 去除单位字符（如 °C、NTU 等）
    const cleaned = s.replace(/[^0-9+\-\.eE]/g, '')
    const n = parseFloat(cleaned)
    return isNaN(n) ? NaN : n
}

// 生成随机数据
const generateRandomData = (count, min, max) => {
	const data = []
	for (let i = 0; i < count; i++) {
		data.push(Math.round((min + Math.random() * (max - min)) * 10) / 10)
	}
	return data
}

// 设备切换
const onDeviceChange = (value) => {
	console.log('切换设备:', value)
	loadData()
}

// 检查警告是否在冷却期内
const isAlertInCooldown = (alertType) => {
	const now = Date.now()
	const lastTriggerTime = alertCooldown.value[alertType]
	
	if (!lastTriggerTime) {
		return false // 从未触发过，不在冷却期
	}
	
	const timeSinceLastTrigger = now - lastTriggerTime
	return timeSinceLastTrigger < COOLDOWN_DURATION
}

// 更新警告冷却时间
const updateAlertCooldown = (alertType) => {
	alertCooldown.value[alertType] = Date.now()
	console.log(`警告冷却已更新: ${alertType}`)
}

// 清理过期的冷却时间（防止内存泄漏）
const cleanupExpiredCooldowns = () => {
	const now = Date.now()
	const expiredTypes = []
	
	for (const [alertType, lastTriggerTime] of Object.entries(alertCooldown.value)) {
		if (now - lastTriggerTime > COOLDOWN_DURATION) {
			expiredTypes.push(alertType)
		}
	}
	
	expiredTypes.forEach(type => {
		delete alertCooldown.value[type]
		console.log(`清理过期冷却: ${type}`)
	})
}

// 跳转到告警详情页面
const goToAlertDetail = () => {
	if (!currentAnomaly.value) {
		uni.showToast({
			title: '没有异常数据',
			icon: 'none'
		})
		return
	}
	
	console.log('跳转到告警详情:', currentAnomaly.value)
	
	// 跳转到告警列表页面，让用户查看所有告警
	uni.switchTab({
		url: '/pages/alert/alert',
		success: () => {
			console.log('跳转到告警页面成功')
		},
		fail: (err) => {
			console.error('跳转失败:', err)
			uni.showToast({
				title: '跳转失败',
				icon: 'none'
			})
		}
	})
}


// 拉取今日历史记录
const fetchToday = async () => {
	try {
        const res = await get('/Device/today', { _t: Date.now() })
		const list = Array.isArray(res.obj) ? res.obj : []
        const mapped = list.map(i => ({
			time: i.time,
			ph: i.pH,
			temp: i.temperature,
			turbidity: i.turbidity
        }))
        // 表格倒序：最近时间在上（按 HH:mm 比较）
        mapped.sort((a, b) => parseHmToMinutes(b.time) - parseHmToMinutes(a.time))
        historyData.value = mapped.slice(0, 20)
		// 用今日数据驱动折线图
		updateChartData(mapped)
	} catch (e) {}
}


// 将 "HH:mm" 转为当天分钟数，用于排序比较
const parseHmToMinutes = (hm) => {
    if (!hm || typeof hm !== 'string') return -1
    const [h, m] = hm.split(':').map(n => Number(n))
    if (isNaN(h) || isNaN(m)) return -1
    return h * 60 + m
}

// 图标/配色
const iconType = (name) => {
    if (name === 'pH值') return 'water'
    if (name === '温度') return 'fire'
    if (name === '浊度') return 'eye'
    return 'circle'
}

const iconClass = (name) => {
    if (name === 'pH值') return 'ph'
    if (name === '温度') return 'temp'
    if (name === '浊度') return 'turbidity'
    return 'default'
}

// 获取严重程度文本
const getSeverityText = (severity) => {
    const severityTexts = {
        low: '轻微',
        medium: '中等',
        high: '严重'
    }
    return severityTexts[severity] || '正常'
}

// 移除手动刷新机制，数据通过WebSocket实时推送

// 格式化时间
const formatTime = (time) => {
	const date = new Date(time)
	const hours = date.getHours().toString().padStart(2, '0')
	const minutes = date.getMinutes().toString().padStart(2, '0')
	return `${hours}:${minutes}`
}
</script>

<style lang="scss" scoped>
.container {
	padding: 20rpx;
	background: #f5f7fa;
	min-height: 100vh;
}

.device-selector {
	margin-bottom: 20rpx;
}

.data-cards {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20rpx;
    margin-bottom: 30rpx;
}

.data-card {
    background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%);
    border-radius: 12rpx;
    padding: 26rpx;
    box-shadow: 0 4rpx 14rpx rgba(0, 0, 0, 0.06);
    border: 1rpx solid #eef2f7;
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.card-left {
    display: flex;
    align-items: center;
    gap: 16rpx;
}

.card-title {
    font-size: 24rpx;
    color: #556370;
    font-weight: 600;
}

.card-icon {
    width: 46rpx;
    height: 46rpx;
    border-radius: 10rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    &.ph { background: #3498db; }
    &.temp { background: #e74c3c; }
    &.turbidity { background: #9b59b6; }
}

.status-indicator {
	width: 12rpx;
	height: 12rpx;
	border-radius: 50%;
	
	&.normal {
		background-color: #27ae60;
	}
	
	&.warning {
		background-color: #f39c12;
	}
	
	&.error {
		background-color: #e74c3c;
	}
}

.card-body {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: 12rpx;
}

.data-value {
    font-size: 40rpx;
    font-weight: 700;
    color: #1f2d3d;
}

.data-unit {
    font-size: 20rpx;
    color: #7a8a99;
    margin-left: 6rpx;
}

.data-hint {
    font-size: 20rpx;
    color: #95a5a6;
}

.warning-standards {
    background: #ffffff;
    border-radius: 12rpx;
    padding: 30rpx;
    margin-bottom: 30rpx;
    box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
    border-left: 6rpx solid #007aff;
}

.standards-header {
    display: flex;
    align-items: center;
    gap: 12rpx;
    margin-bottom: 20rpx;
}

.standards-title {
    font-size: 28rpx;
    font-weight: bold;
    color: #2c3e50;
}

.standards-content {
    display: flex;
    flex-direction: column;
    gap: 16rpx;
}

.standard-item {
    display: flex;
    align-items: center;
    gap: 8rpx;
    padding: 12rpx 16rpx;
    background: #f8f9fa;
    border-radius: 8rpx;
}

.standard-label {
    font-size: 24rpx;
    color: #495057;
    font-weight: 600;
    min-width: 80rpx;
}

.standard-range {
    font-size: 24rpx;
    font-weight: bold;
    
    &.normal {
        color: #27ae60;
    }
    
    &.warning {
        color: #e74c3c;
    }
}

.standard-unit {
    font-size: 22rpx;
    color: #6c757d;
}

.anomaly-alert {
    background: #fff5f5;
    border: 2rpx solid #fed7d7;
    border-radius: 12rpx;
    margin: 20rpx;
    padding: 20rpx;
    box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
    cursor: pointer;
    transition: all 0.3s ease;
}

.anomaly-alert:active {
    background: #fed7d7;
    transform: scale(0.98);
}

.anomaly-alert-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12rpx;
}

.anomaly-alert-text {
    flex: 1;
    font-size: 28rpx;
    font-weight: bold;
    color: #e74c3c;
}


.card-footer {
	display: flex;
	justify-content: flex-end;
}

.update-time {
	font-size: 20rpx;
	color: #95a5a6;
}

.chart-section {
	background: #ffffff;
	border-radius: 12rpx;
	padding: 30rpx;
	margin-bottom: 30rpx;
	box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}

.chart-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 20rpx;
}

.chart-title {
	font-size: 28rpx;
	font-weight: bold;
	color: #2c3e50;
}


.chart-container {
	height: 450rpx;
	background: #f8f9fa;
	border-radius: 8rpx;
	overflow: hidden;
}

.chart-canvas {
	width: 100%;
	height: 100%;
}

.chart-item {
	margin-bottom: 40rpx;
	background: #ffffff;
	border-radius: 12rpx;
	padding: 30rpx;
	box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}

.chart-item-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 15rpx;
}

.chart-item-title {
	font-size: 28rpx;
	font-weight: bold;
	color: #2c3e50;
}

.chart-item-unit {
	font-size: 22rpx;
	color: #7f8c8d;
	background: #f8f9fa;
	padding: 6rpx 16rpx;
	border-radius: 12rpx;
}

.table-section {
	background: #ffffff;
	border-radius: 12rpx;
	padding: 30rpx;
	box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}

.table-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 20rpx;
}

.table-title {
	font-size: 28rpx;
	font-weight: bold;
	color: #2c3e50;
}

.connection-status {
	padding: 8rpx 16rpx;
	border-radius: 20rpx;
	font-size: 22rpx;
	
	&.connected {
		background: #d4edda;
		color: #155724;
	}
	
	&.disconnected {
		background: #f8d7da;
		color: #721c24;
	}
}

.status-text {
	font-size: 22rpx;
}

.table-content {
	overflow-x: auto;
}

.table-row {
	display: flex;
	padding: 20rpx 0;
	border-bottom: 1rpx solid #ecf0f1;
	
	&.header {
		font-weight: bold;
		background: #f8f9fa;
		margin: 0 -30rpx;
		padding: 20rpx 30rpx;
	}
	
	&:last-child {
		border-bottom: none;
	}
}

.col-time {
	width: 120rpx;
	font-size: 22rpx;
	color: #7f8c8d;
}

.col-ph, .col-temp, .col-turb, .col-o2 {
	width: 100rpx;
	font-size: 22rpx;
	color: #2c3e50;
	text-align: center;
}

.col-status {
	width: 80rpx;
	font-size: 20rpx;
	text-align: center;
	
	&.normal {
		color: #27ae60;
	}
	
	&.warning {
		color: #e74c3c;
	}
}
</style>